import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.svm import SVR
from sklearn.ensemble import GradientBoostingRegressor
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error

plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用SimHei字体
plt.rcParams['axes.unicode_minus'] = False  # 正确显示负号

# 1. 读取训练数据，只读取必要的列
columns_to_read = ['材料', '温度，oC', '频率，Hz', '磁芯损耗，w/m3', '励磁波形']
train_data = pd.read_excel('合并数据集.xlsx', usecols=columns_to_read, engine='openpyxl')

# 提取所需特征和目标变量
material = pd.Categorical(train_data['材料']).codes  # 材料：材料1、材料2、材料3、材料4
temperature = train_data['温度，oC']                  # 温度：25、50、70、90摄氏度
frequency = train_data['频率，Hz']                    # 频率：50000—500000 Hz
core_loss = train_data['磁芯损耗，w/m3']             # 磁芯损耗，目标变量
waveform = pd.Categorical(train_data['励磁波形']).codes  # 励磁波形：正弦波、三角波、梯形波

# 提取磁通密度峰值（假设磁通密度从第6列到最后列）
magnetic_density = train_data.iloc[:, 5:].values      # 提取磁通密度数据
Bm_train = np.max(magnetic_density, axis=1)           # 提取每行（每个样本）的磁通密度峰值

# 构建特征矩阵（输入变量），加入磁通密度峰值
X_train = np.column_stack([material, temperature, frequency, waveform, Bm_train])

# 2. 线性回归模型
linear_model = LinearRegression()
linear_model.fit(X_train, core_loss)
linear_pred_train = linear_model.predict(X_train)

# 3. 支持向量机回归（SVR）模型
svr_model = SVR(kernel='rbf', C=100, gamma=0.1)
svr_model.fit(X_train, core_loss)
svr_pred_train = svr_model.predict(X_train)

# 4. 梯度提升回归模型（增强泛化能力）
gbr_model = GradientBoostingRegressor(
    n_estimators=100,            # 树的数量
    learning_rate=0.1,           # 学习率
    max_depth=3,                 # 最大深度
    min_samples_split=10,        # 最小样本划分数
    min_samples_leaf=5,          # 最小叶子节点样本数
    subsample=0.8,               # 数据子样本比例
    random_state=1               # 随机种子
)
gbr_model.fit(X_train, core_loss)
gbr_pred_train = gbr_model.predict(X_train)

# 输出各模型的 R²得分
linear_score = linear_model.score(X_train, core_loss)
svr_score = svr_model.score(X_train, core_loss)
gbr_score = gbr_model.score(X_train, core_loss)

# 计算 RMSE
linear_rmse = np.sqrt(mean_squared_error(core_loss, linear_pred_train))
svr_rmse = np.sqrt(mean_squared_error(core_loss, svr_pred_train))
gbr_rmse = np.sqrt(mean_squared_error(core_loss, gbr_pred_train))

print(f'线性回归模型的R²得分: {linear_score}, RMSE: {linear_rmse}')
print(f'SVR模型的R²得分: {svr_score}, RMSE: {svr_rmse}')
print(f'梯度提升模型的R²得分: {gbr_score}, RMSE: {gbr_rmse}')

# 读取测试数据，使用相同的列
test_data = pd.read_excel('附件三（测试集）.xlsx', usecols=columns_to_read, engine='openpyxl')

# 提取测试数据中的特征
material_test = pd.Categorical(test_data['材料']).codes   # 材料
temperature_test = test_data['温度，oC']                      # 温度
frequency_test = test_data['频率，Hz']                        # 频率
waveform_test = pd.Categorical(test_data['励磁波形']).codes   # 励磁波形

# 提取测试数据中的磁通密度峰值
magnetic_density_test = test_data.iloc[:, 5:].values      # 提取磁通密度数据
Bm_test = np.max(magnetic_density_test, axis=1)           # 提取每行（每个样本）的磁通密度峰值

# 构建测试数据的特征矩阵，加入磁通密度峰值
X_test = np.column_stack([material_test, temperature_test, frequency_test, waveform_test, Bm_test])

# 预测测试集结果
linear_pred = linear_model.predict(X_test)
svr_pred = svr_model.predict(X_test)
gbr_pred = gbr_model.predict(X_test)

# 5. 结果的加权平均（根据模型的 R² 得分）
total_score = linear_score + svr_score + gbr_score
linear_weight = linear_score / total_score
svr_weight = svr_score / total_score
gbr_weight = gbr_score / total_score

weighted_pred = (linear_weight * linear_pred + svr_weight * svr_pred + gbr_weight * gbr_pred)

# 6. 保存预测结果为 Excel 文件
predicted_core_loss_table = pd.DataFrame({
    'LinearRegression': linear_pred,
    'SVR': svr_pred,
    'GradientBoosting': gbr_pred,
    'WeightedPrediction': weighted_pred
})

# 保存到 Excel 文件
predicted_core_loss_table.to_excel('问题四加权预测磁芯损耗结果.xlsx', index=False)
print('预测结果已成功保存为 问题四加权预测磁芯损耗结果.xlsx')

# 7. 可视化各个模型和加权模型的预测结果
plt.figure(figsize=(10, 6))
plt.plot(linear_pred, label='线性回归', linestyle='--')
plt.plot(svr_pred, label='SVR', linestyle='-.')
plt.plot(gbr_pred, label='梯度提升回归', linestyle=':')
plt.plot(weighted_pred, label='加权预测', linestyle='-', color='r', linewidth=2)
plt.xlabel('样本编号')
plt.ylabel('预测磁芯损耗 (W/m^3)')
plt.title('磁芯损耗预测结果 - 不同模型与加权结果')
plt.legend()
plt.grid(True)
plt.show()
